﻿using IdentityServer4.Models;
using IdentityServer4.Services;
using IdentityServer4.Validation;
using System.Security.Claims;

namespace Api.IdentityServer4
{
    public class RefreshTokenService : IRefreshTokenService
    {    
        /// <summary>
         /// 模拟RefreshToken存在缓存中
         /// </summary>
        private readonly static Dictionary<string, RefreshToken> _refreshTokens = new Dictionary<string, RefreshToken>();

        public async Task<string> CreateRefreshTokenAsync(ClaimsPrincipal subject, Token accessToken, Client client)
        {
            var handle = Guid.NewGuid().ToString();
            var refreshToken = new RefreshToken
            {
                AccessToken = accessToken,
                CreationTime = DateTime.UtcNow,
                Lifetime = client.RefreshTokenExpiration == TokenExpiration.Sliding ? client.SlidingRefreshTokenLifetime : client.AbsoluteRefreshTokenLifetime,
                //Subject = subject,
                Version = 1
            };
            _refreshTokens[handle] = refreshToken;
            return await Task.FromResult(handle);
        }

        public async Task<string> UpdateRefreshTokenAsync(string handle, RefreshToken refreshToken, Client client)
        {
            if (!_refreshTokens.ContainsKey(handle))
            {
                throw new ArgumentException("Invalid refresh token handle");
            }

            _refreshTokens[handle] = refreshToken;
            return await Task.FromResult(handle);
        }

        public async Task<TokenValidationResult> ValidateRefreshTokenAsync(string token, Client client)
        {
            if (!_refreshTokens.TryGetValue(token, out var refreshToken))
            {
                return await Task.FromResult(new TokenValidationResult
                {
                    IsError = true,
                    Error = "Invalid refresh token"
                });
            }

            if (refreshToken.AccessToken.ClientId != client.ClientId)
            {
                return await Task.FromResult(new TokenValidationResult
                {
                    IsError = true,
                    Error = "Refresh token does not belong to the client"
                });
            }

            if (DateTime.UtcNow > refreshToken.CreationTime.AddSeconds(refreshToken.Lifetime))
            {
                return await Task.FromResult(new TokenValidationResult
                {
                    IsError = true,
                    Error = "Refresh token has expired"
                });
            }

            return await Task.FromResult(new TokenValidationResult
            {
                IsError = false,
                RefreshToken = refreshToken
            });
        }
    }
}
